/**
 * 
 */

function getSibling(me, parent, parChildAttrName) {
    var sibling;
    var childAttrName = (parChildAttrName ? parChildAttrName : "child");
    
    for (var i = 0; parent && parent[childAttrName] && i < parent[childAttrName].length; i++) {
        if (parent[childAttrName][i] == me) {
            // 마지막 노드 이전일 경우만 sibling이 존재함
            if (i < parent[childAttrName].length - 1) { sibling = parent[childAttrName][i + 1]; }
            break;
        }   
    }
    
    return sibling;
}

function navigateDepthFirst(data, handler, parChildAttrName) {
    var childAttrName = (parChildAttrName ? parChildAttrName : "child");
    var done = [];
    var stack = [];
    var ref = data;
    
    while (ref) {
        if ($.inArray(ref, done) == -1) { handler(ref, stack); }
        
        if ($.inArray(ref, done) == -1 && ref[childAttrName] && ref[childAttrName].length > 0) {
            stack.push(ref);
            done.push(ref);
            ref = ref[childAttrName][0];
        } else {
            var parent = stack.peek();
            var sibling = getSibling(ref, parent);
            
            if (sibling) {
                ref = sibling;
            } else {
                ref = stack.pop();
            }
        }
    }
}    

function searchDepthFirst(data, handler, parChildAttrName) {
    var childAttrName = (parChildAttrName ? parChildAttrName : "child");
    var done = [];
    var stack = [];
    var ref = data;
    while (ref) {
        if (handler(ref)) { return ref; }   
    
        if ($.inArray(ref, done) == -1 && ref[childAttrName] && ref[childAttrName].length > 0) {
            stack.push(ref);
            done.push(ref);
            ref = ref[childAttrName][0];
        } else {
            var parent = stack.peek();
            var sibling = getSibling(ref, parent, childAttrName);
            
            if (sibling) {
                ref = sibling;
            } else {
                ref = stack.pop();
            }
        }
    }
    return;
}

